#include <iostream>
#include <string>
#include <typeinfo>
#include <typeindex>
#include <cassert>

namespace MyAny
{
    class Any
    {
        class placeholder // 包含纯虚函数，是抽象类，不能直接实例化对象
        {
        public:
            virtual ~placeholder() {
                /*placeholder 类是一个纯虚类，
                它的析构函数需要提供一个实现，否则会导致链接错误。
                纯虚析构函数的实现通常是一个空函数体。*/
            }
            virtual const std::type_info &type() = 0; // 返回参数的类型
            virtual placeholder *clone() = 0;   // 克隆出一个相同的对象，实现深拷贝
        };

        template <typename T>
        class subholder : public placeholder // 子类
        {
        public:
            subholder(const T &operand) : _val(operand) {}
            ~subholder() {}                       // 析构
            const std::type_info &type() override // 返回对象的数据类型
            {
                return typeid(T);
            }
            placeholder *clone() override
            {
                return new subholder(_val);
            }

        public:
            T _val; // 数据对象
        };

    private:
        placeholder *_content; // 定义基类指针
    public:
        Any() : _content(nullptr) {};

        template <typename T>
        Any(const T &operand) : _content(new subholder<T>(operand)){};

        bool has_value() // 是否已经有值
        {
            return _content != nullptr;
        }

        Any(const Any &operand)
        {
            _content = operand._content == nullptr ? nullptr : operand._content->clone();
        }

        template <typename T>
        Any &operator=(const T &operand)
        {
            /*为operand构建⼀个临时对象出来，然后进⾏交换，这样临时对象销毁的时候，顺带原先
            保存的placeholder也会被销毁*/
            Any(operand).swap(*this);
            return *this;
        }

        Any &operator=(Any operand) // 构造一个新的临时对象，直接交换资源即可
        {
            
            // if(has_value()) {delete _content; _content = nullptr;} 使用拷贝交换惯用法，已经将资源托管给临时对象，无需这一步
            swap(operand);
            return *this;
        }
        void swap(Any &operand)
        {
            std::swap(_content, operand._content);
        }

        const std::type_info &type()
        {
            return _content->type();
        }

        template <typename T>
        T *get_val()
        {
            if (typeid(T) != type())
                assert(nullptr);
            return &(((subholder<T> *)_content)->_val);
        }
        ~Any()
        {
            if(has_value()) delete _content;
            _content = nullptr;
        }
    };

    template <typename T>
    T any_cast(Any &operand)
    {
        if (typeid(T) != operand.type())
            throw("type mismatch");
        return *(operand.get_val<T>());
    }

    template <typename T>
    T *any_cast(Any *operand)
    {
        if (typeid(T) != operand->type())
            throw("type mismatch");
        return operand->get_val<T>();
    }
}

class Test
{
public:
    std::string _data;

public:
    Test(const std::string &data) : _data(data) { std::cout << "构造" << _data << std::endl; }
    Test(const Test &other)
    {
        _data = other._data;
        std::cout << "拷⻉" << _data << std::endl;
    }
    ~Test() { std::cout << "析构" << _data << std::endl; }
};

using namespace MyAny;
int main()
{
    // 测试用例1
    Any a;
    a = std::string("asdasdasd");
    std::string ret = any_cast<std::string>(a);
    std::cout << ret << std::endl;
     
    Any b = 10;
    std::cout << any_cast<int>(b) << std::endl;

    b = a;
    std::cout << *b.get_val<std::string>() << std::endl;
    std::cout << any_cast<std::string>(a) << std::endl;

    std::string s = "asdasdsads\0adsasdasd";
    std::cout << s << std::endl;

    // // 测试用例2
    // Any a;
    // {
    //     Test t("1");
    //     a = t;
    // }
    // while(1);
    return 0;
}


// 勘误记录
// date 2024.01.09
// 1、经delete后的指针对象虽然资源已经被清除，但是其指针的值不会自动设置为空指针，需要手动设置指针=nullptr，否则会引发悬空指针的问题
// 2、拷贝交换惯用法的原理就是创建一个局部域或临时对象，使用swap交换当前对象与临时对象的管理资源。
// 在临时对象生命周期到达时，可以自动清除自己内部的资源，这也要求析构函数一定要设计完善
// 虚基类的析构函数一定要提供一个实现——通常是空函数

// 反思：c++内容已有遗忘，项目完成后需及时复习